﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Bymed.SpineScan.Service.Interface
{
    /// <summary>
    /// An instance of IService against the specific DataModel type and provides standard CRUD operation only.
    /// </summary>
    public interface IService<T> where T : class
    {
        /// <summary>
        /// Add new entity.
        /// </summary>
        /// <param name="entity">The new entity will be added into database.</param>
        /// <returns>The id of the new added entity.</returns>
        T Add(T entity);

        /// <summary>
        /// Add new entity list.
        /// </summary>
        /// <param name="entities">The new entity list will be added into database.</param>
        /// <returns>The new added entity list.</returns>
        IList<T> Add(IEnumerable<T> entities);

        // <summary>
        /// Get entity by id.
        /// </summary>
        /// <param name="id">The specified id.</param>
        /// <returns>The matched data.</returns>
        T Get(object id);

        /// <summary>
        /// Query data by lambda expression.
        /// </summary>
        /// <param name="expression">The lambda expression that accepts TDataModel and return boolean.</param>
        /// <returns>An IList list of data.</returns>
        IList<T> Query(Expression<Func<T, bool>> expression);

        /// <summary>
        /// Query data by lambda expression.
        /// </summary>
        /// <typeparam name="TResult">The type of the value returned by selector.</typeparam>
        /// <param name="expression">The lambda expression that accepts TDataModel and return boolean.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <returns>An IList list of data.</returns>
        IList<TResult> Query<TResult>(Expression<Func<T, bool>> expression, Expression<Func<T, TResult>> selector);

        /// <summary>
        /// Get all data. You also can query the data later since the returned result is a IList collection.
        /// </summary>
        /// <returns>An IList collection of data.</returns>
        IList<T> GetAll();

        /// <summary>
        /// Get the data's count by using provided lambda expression.
        /// </summary>
        /// <param name="expression">The lambda expression that accepts T and return boolean.</param>
        /// <returns>The data's count.</returns>
        int GetRowCount(Expression<Func<T, bool>> expression);

        /// <summary>
        /// Update existing entity.
        /// </summary>
        /// <param name="entity">The entity will be updated.</param>
        void Update(T entity);

        /// <summary>
        /// Update existing entity list.
        /// </summary>
        /// <param name="entities">The entity list will be updated.</param>
        void Update(IEnumerable<T> entities);

        /// <summary>
        /// Add or update entity.
        /// </summary>
        /// <param name="entity">The entity will be updated if it is existing or added if it cannot be found.</param>
        void AddOrUpdate(T entity);

        /// <summary>
        /// Add or update entity list.
        /// </summary>
        /// <param name="entities">The entity list will be updated if it is existing or added if it cannot be found.</param>
        void AddOrUpdate(IEnumerable<T> entities);

        /// <summary>
        /// Delete the specified entity.
        /// </summary>
        /// <param name="entity">The entity will be deleted from database.</param>
        void Delete(T entity);

        /// <summary>
        /// Delete the specified entity list.
        /// </summary>
        /// <param name="entities">The entity list will be deleted from database.</param>
        void Delete(IEnumerable<T> entities);
    }
}
